/*
 * TMap Designer - A Thematic Map design software
 * Copyright (C) 2006 World Health Organization
 * http://www.who.int
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
package who.tmap.services;

import java.io.IOException;
import java.net.URL;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

import org.apache.log4j.Logger;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import who.tmap.imp.ODBCDSNLessImportAdapter;

/**
 * A helper dedicated to ODBC DSN connection
 * Used by the Attributes Wizard
 * @author stl
 *
 */
public class ODBCDSNLessService {
	
	// Used in the GUI 
	public static final String ODBC_ACCESS_NAME ="MS Access";
	
    private static Logger logger = Logger.getLogger(ODBCDSNLessService.class);
    
    private static ODBCDSNLessService instance =null;
    
    public static enum ODBCProps { 
    	HOST (ODBCDSNLessImportAdapter.HOST), 
    	PORT (ODBCDSNLessImportAdapter.PORT), 
    	HOST_PORT (ODBCDSNLessImportAdapter.HOST_PORT), 
    	SERVER (ODBCDSNLessImportAdapter.SERVER), 
    	DB( ODBCDSNLessImportAdapter.DB ), 
    	DB_LOCATION (ODBCDSNLessImportAdapter.DB_LOCATION), 
    	UID( ODBCDSNLessImportAdapter.UID), 
    	PWD( ODBCDSNLessImportAdapter.PWD), 
    	SID( ODBCDSNLessImportAdapter.SID),
    	EXT( ODBCDSNLessImportAdapter.EXT ),
    	CAST_STRING( ODBCDSNLessImportAdapter.CAST_STRING ),
    	USE_BRACKETS( ODBCDSNLessImportAdapter.USE_BRACKETS );
    
    	private final String name;
    	
    	ODBCProps( String name ) {
    		this.name =name;
    	}
    	
    	public String getName() {
    		return name;
    	}
    
    }
    
	private static final String ODBC_CONFIG_FILE ="/ODBCDSNLess.xml";
	private static String[] keys =null;
	private static Map<String, ODBCDSNLessDef> props =null;
	
    /**
     * Private constructor because it is a singleton
     *
     */
    private ODBCDSNLessService() {
		try {
			loadODBCConfig( getClass().getResource( ODBC_CONFIG_FILE ) );
		} catch (Exception e) {
			logger.error( e );
		}    	
    }
    
    /**
     * Lazy instanciation
     * @return
     */
    public static synchronized ODBCDSNLessService getInstance() {
        if ( instance == null ) {
            instance =new ODBCDSNLessService();
        }
        
        return instance;
    }	

	
	@SuppressWarnings("unchecked")
	private void loadODBCConfig( URL url ) throws IOException, JDOMException {
		props =new TreeMap<String, ODBCDSNLessDef>( String.CASE_INSENSITIVE_ORDER );
		
        SAXBuilder builder = new SAXBuilder();
        builder.setIgnoringElementContentWhitespace(true);
        Document doc = builder.build( url );
        
        Element rootElt =doc.getRootElement();
        
        Iterator it =rootElt.getChildren().iterator();
        while( it.hasNext() ) {
        	Element elt =(Element)it.next();
        	
        	ODBCDSNLessDef dsnLess =new ODBCDSNLessDef();
        	
        	Map<String, String> attrs =new TreeMap<String, String>();
        	dsnLess.setAttrs( attrs );
        
        	Iterator itAttr =elt.getAttributes().iterator();
        	while( itAttr.hasNext() ) {
        		Attribute attr =(Attribute)itAttr.next();
        		
        		if ( !attr.getName().equals( "name" ) 
        				&& !attr.getName().equals( "driver" ) ) {
        			attrs.put( attr.getName(), attr.getValue() );
        		}
        	}
        	
        	dsnLess.setName( elt.getAttributeValue( "name" ) );
        	dsnLess.setDriver( elt.getAttributeValue( "driver" ) );        	
        	
        	props.put( dsnLess.getName(), dsnLess );
        }
        
		keys =new String[ props.keySet().size() ];
		props.keySet().toArray(keys);        
	}
	
	public String[] getConfigKeys() {
		return keys;
	}
	
	public ODBCDSNLessDef getConfigValue( String key ) {
		return props.get( key );
	}
	
	/**
	 * Build a JDBC ODBC DSN-less connection string
	 * @param name name of the ODBC database
	 * @param values 
	 * @return the connection string
	 */
	public String getConnectionString( String name, Map<String, String> values ) {
		StringBuffer str =new StringBuffer( "jdbc:odbc:driver=" );
		
		ODBCDSNLessDef dsnLess =getConfigValue( name );
		
		str.append( dsnLess.getDriver() ).append( ";" );
		
		for( String key : dsnLess.getAttrs().keySet() ) {
			if ( !ODBCProps.EXT.getName().equals( key )
					&& !ODBCProps.CAST_STRING.getName().equals( key )
					&& !ODBCProps.USE_BRACKETS.getName().equals( key ) ) {					
				String realKey =dsnLess.getAttrs().get( key );
				String value =values.get( key );
				if ( value == null ) {
					value ="";
				}
			
				str.append( realKey ).append( "=" ).append( value ).append( ";" );
			}
		}
		
		logger.debug( "connection string=" + str );
		
		return str.toString();
		
	}
}
